package com.lib.common.base.web

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.net.http.SslError
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import android.view.View
import android.webkit.*
import android.widget.LinearLayout
import android.widget.ProgressBar
import com.lib.common.base.mvvm.CommonViewModelFragment
import com.lib.framework.entity.Event
import com.lib.framework.helper.permission.PermissionHelper
import com.lib.framework.manager.ContextManager
import com.lib.framework.manager.LogManager
import wendu.dsbridge.DWebView
import wendu.dsbridge.OnReturnValue


/**
 * 基本网页 Fragment
 *
 * @author keanbin
 */
abstract class BaseWebFragment<T : BaseWebViewModel> : CommonViewModelFragment<T>() {

    companion object {

        /**
         * 事件标记范围 99600 ~ 99699
         */
        const val EVENT_LOAD_URL = 99600 // 加载网页
        const val EVENT_RELOAD = 99601 // 重新导入
        const val EVENT_SHOW_ERROR_VIEW = 99602 // 显示错误提示页面

    }

    protected var mWebView: DWebView? = null
    protected var mProgressBar: ProgressBar? = null
    protected var mErrorView: View? = null

    private var mHandler = Handler(Looper.getMainLooper())

    /**
     * H5 获取图片的回调
     */
    private var mUpLoadsCallback: ValueCallback<Array<Uri>>? = null
    private var mUpLoadCallback: ValueCallback<Uri>? = null


    override fun initView() {
        initWebView()
    }

    /**
     * 初始化 WebView
     */
    @SuppressLint("SetJavaScriptEnabled")
    private fun initWebView() {
        val rootView = view ?: return

        getProgressBarId()?.let {
            mProgressBar = rootView.findViewById(it)
        }

        mWebView = rootView.findViewById(getWebViewId())
        mWebView?.let {
            val ua = it.settings.userAgentString
            it.settings.userAgentString = "$ua xiangwushuo/1.0.0"
            it.settings.domStorageEnabled = true //设置适应H5

            it.isHorizontalScrollBarEnabled = false //水平不显示
            it.isVerticalScrollBarEnabled = false //垂直不显示

            // 设置缓存
            it.settings?.cacheMode = WebSettings.LOAD_DEFAULT
            it.settings?.setAppCacheEnabled(true)
            it.settings?.javaScriptEnabled = true
            it.settings?.domStorageEnabled = true
            it.settings?.layoutAlgorithm = WebSettings.LayoutAlgorithm.NORMAL


            // dsbridge： 添加 Javascript 对象，供 Javascript 调用 原生方法
            it.addJavascriptObject(mViewModel.mJsToNativeBridge, null)

            // dsbridge： 原生 调用 Javascript 方法
            it.callHandler("addValue", arrayOf(3, 4), OnReturnValue<Int> { retValue ->
                LogManager.d("jsbridge", "call succeed,return value is $retValue")
            })

            // android原生方式：这里客户端 主动执行 Javascript 调用原生的方法，比如网页加载完成之后，获取网页的源代码
            it.addJavascriptInterface(InJavaScriptLocalObj(), "java_obj")


            it.webChromeClient = object : WebChromeClient() {
                override fun onProgressChanged(view: WebView?, newProgress: Int) {
                    super.onProgressChanged(view, newProgress)

                    if (newProgress < 100) {
                        mHandler.removeCallbacks(mHideProgressBarRunnable)
                        mProgressBar?.progress = newProgress
                        mProgressBar?.visibility = View.VISIBLE
                    } else {
                        mProgressBar?.progress = 100
                        mHandler.postDelayed(mHideProgressBarRunnable, 1000)
                    }
                }

                /**
                 * 以下是 H5 获取图片
                 */
                /**
                 * {@inheritDoc}
                 * 安卓3.0-
                 */
                fun openFileChooser(uploadMsg: ValueCallback<Uri>) {
                    openFileChooser(uploadMsg, "")
                }

                /**
                 * {@inheritDoc}
                 * 安卓3.0 - 4.0
                 */
                fun openFileChooser(
                    uploadMsg: ValueCallback<Uri>,
                    acceptType: String
                ) {
                    mUpLoadCallback = uploadMsg
                    var i: Intent? = null
                    if (Build.VERSION.SDK_INT < 19) {
                        i = Intent(Intent.ACTION_GET_CONTENT)
                        i.type = ("image/*")
                    } else {
                        i = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    }
                    startActivityForResult(Intent.createChooser(i, "选择图片"), 2001);
                }

                fun openFileChooser(
                    uploadMsg: ValueCallback<Uri>,
                    acceptType: String,
                    capture: String
                ) {
                    mUpLoadCallback = uploadMsg
                    openImageChooserActivity()

                    openFileChooser(uploadMsg, acceptType)
                }

                override fun onShowFileChooser(
                    webView: WebView?,
                    filePathCallback: ValueCallback<Array<Uri>>?,
                    fileChooserParams: FileChooserParams?
                ): Boolean {
                    mUpLoadsCallback = filePathCallback
                    chooseImage()
                    return true
                }
            }

            it.webViewClient = object : WebViewClient() {

                override fun shouldOverrideUrlLoading(
                    view: WebView?,
                    request: WebResourceRequest?
                ): Boolean {
                    if (super.shouldOverrideUrlLoading(view, request)) {
//                        request?.url?.let {
//                            mViewModel.mCurrentUrl = it.
//                        }
                        return true
                    }


                    return false
                }

                override fun onPageFinished(view: WebView?, url: String?) {
                    super.onPageFinished(view, url)

                    val title = view?.title
                    if (title != null && title.isNotEmpty()) {
                        onChangePageTitle(title)
                    }

                    // 使用 js 注入 获取 网页 内容
                    mWebView?.loadUrl(
                        "javascript:window.java_obj.getSource('<head>'+" + "document.getElementsByTagName('html')[0].innerHTML+'</head>');")
                }

                override fun onReceivedSslError(
                    view: WebView?, handler: SslErrorHandler?,
                    error: SslError?
                ) {
                    handler?.proceed() //接受证书
                }

                override fun onReceivedError(
                    view: WebView?, request: WebResourceRequest?,
                    error: WebResourceError?
                ) {
                    onPageError(view, request, error)
                }
            }
        }
    }

    /**
     * 网页标题改变
     */
    protected open fun onChangePageTitle(title: String) {
        mViewModel.onChangePageTitle(title)
    }

    /**
     * 页面出错
     */
    protected open fun onPageError(
        view: WebView?, request: WebResourceRequest?,
        error: WebResourceError?
    ) {
        mViewModel.onPageError(view, request, error)
    }

    /**
     * 创建 错误页面
     */
    protected open fun createErrorView(context: Context): View {
        val errorView = WebErrorView(context)
        errorView.mOnRefreshClickListener = object : WebErrorView.OnRefreshClickListener {
            override fun onRefreshClick() {
                reloadUrl()
            }
        }

        return errorView
    }

    /**
     * 显示错误页面
     */
    protected fun showErrorView() {
        val lp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.MATCH_PARENT)
        val context = context
        if (mErrorView == null && context != null) {
            mErrorView = createErrorView(context)
            mWebView?.addView(mErrorView, 0, lp)
        }
    }

    /**
     * 隐藏错误页面
     */
    protected fun dismissErrorView() {
        if (mErrorView != null) {
            mWebView?.removeView(mErrorView)
            mErrorView = null
        }
    }

    /**
     * 隐藏 进度条 runnable
     */
    private val mHideProgressBarRunnable = Runnable {
        mProgressBar?.progress = 0
        mProgressBar?.visibility = View.GONE
    }

    /**
     * 使用webView加载网页
     */
    protected fun webViewLoadUrl(url: String) {
        mWebView?.loadUrl(url)
        mViewModel.mCurrentUrl = url
        dismissErrorView()
    }

    /**
     * 重新加载网页
     */
    protected fun reloadUrl() {
        mWebView?.reload()
        dismissErrorView()
    }

    /**
     * 获取 WebView 的 id
     */
    abstract fun getWebViewId(): Int

    /**
     * 获取 ProgressBar 的 id
     */
    abstract fun getProgressBarId(): Int?

    override fun dealEvent(event: Event?): Boolean {
        when (event?.code) {
            EVENT_SHOW_ERROR_VIEW -> {
                showErrorView()
                return true
            }

            EVENT_RELOAD -> {
                reloadUrl()
                return true
            }

            EVENT_LOAD_URL -> {
                val url = event.extraObj
                if (url is String) {
                    webViewLoadUrl(url)
                }

                return true
            }
        }

        return super.dealEvent(event)
    }

    /**
     * 清空 Cookie
     */
    protected fun clearCookie() {
        CookieSyncManager.createInstance(
            ContextManager.applicationContext)  //Create a singleton CookieSyncManager within a context
        val cookieManager = CookieManager.getInstance() // the singleton CookieManager instance
        cookieManager.removeAllCookie()// Removes all cookies.
        CookieSyncManager.getInstance().sync() // forces sync manager to sync now
    }

    /**
     * 销毁 WebView
     */
    open protected fun destroyWebView() {
        mWebView?.webChromeClient = null
        mWebView?.webViewClient = null
        mWebView?.settings?.javaScriptEnabled = false
        mWebView?.clearCache(true)

        //为了使WebView退出时音频或视频关闭
        mWebView?.destroy()
    }

    override fun onDestroy() {
        super.onDestroy()

        destroyWebView()
    }

    /**
     * 注入 Javascript 的 java 对象
     * 这里客户端 主动执行 Javascript 调用原生的方法，比如网页加载完成之后，获取网页的源代码
     */
    internal inner class InJavaScriptLocalObj {
        @JavascriptInterface
        fun getSource(html: String) {
            LogManager.i(mTag, "html = $html")
        }
    }

    /**
     * 后退处理
     */
    fun onBackPressed(): Boolean {
        if (mWebView?.canGoBack() == true) {
            mWebView?.goBack()
            return true
        }

        return false
    }

    /**
     * 以下H5 获取图片需要
     */
    /**
     * js选择图片
     */
    fun chooseImage() {
        val activity = activity ?: return
        PermissionHelper.requestPermissions(
            this,
            object :
                PermissionHelper.OnPermissionListener {
                override fun onGranted() {
                    openImageChooserActivity()
                }

                override fun onDenied() {
                    mUpLoadsCallback?.let {
                        it.onReceiveValue(null)
                        mUpLoadsCallback = null
                    }
                    showPrompt("获取图片，需要访问本地存储权限")
                }
            },
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE
        )
    }

    /**
     *  选择图片
     */
    fun openImageChooserActivity() {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.type = "image/*"
        startActivityForResult(
            Intent.createChooser(
                intent,
                "选择上传的图片"
            ), 2001
        )
    }

    override fun onActivityResult(
        requestCode: Int,
        resultCode: Int,
        data: Intent?
    ) {
        if (requestCode == 2001 && resultCode == Activity.RESULT_OK) {
            mUpLoadsCallback?.let { upload ->
                data?.let {
                    val dataString = it.dataString
                    dataString?.let {
                        val uri = Uri.parse(dataString)
                        uri?.let { uri ->
                            val results = arrayOf(uri)
                            upload.onReceiveValue(results)
                            mUpLoadsCallback = null
                        }
                    }
                }
            }

            mUpLoadCallback?.let { upload ->
                val uri = data?.data
                uri?.let {
                    upload.onReceiveValue(it)
                    mUpLoadsCallback = null
                }
            }
        } else if (requestCode == 2001 && resultCode == Activity.RESULT_CANCELED) {
            mUpLoadsCallback?.let {
                it.onReceiveValue(null)
                mUpLoadsCallback = null
            }
        }

        super.onActivityResult(requestCode, resultCode, data)
    }
}
